<template>
  <div class="app-container">
    <el-row>
      <el-col>
        <el-button class="margin-right" type="text" icon="el-icon-refresh" @click="reloadAllConnects"/>

        <el-select v-model="connParam.connName" @change="switchConnect" size="small">
          <el-option v-for="connect in connects" :key="connect" :value="connect" :label="connect"/>
        </el-select>
        <el-select v-model="connParam.index" @change="switchIndex"  size="small" :disabled="tabs.dashboard.connInfo.redisRunMode === 'cluster'" style="width: 60px">
          <el-option v-for="db in dbsComputed" :key="db" :value="db" :label="db" />
        </el-select>
      </el-col>
    </el-row>

    <el-tabs :active-name="tabs.activeTabName" @tab-click="switchTab" >
      <!-- 监控运行模式, 节点信息 -->
      <el-tab-pane name="dashboard" label="监控总览">
        <p class=" text-forestgreen">点击节点显示节点信息</p>
        <p>运行模式: <b>{{tabs.dashboard.connInfo.redisRunMode}}</b></p>
        <el-row>
          <el-col :span="8">
            <el-tree :data="tabs.dashboard.connInfo.masterNodes" @node-click="clickNode" :expand-on-click-node="false" :default-expand-all="true" :props="defaultProps" >
              <div class="custom-tree-node" slot-scope="{ node, data }">
                <b class="margin-right">{{data.role}}</b>
                <span v-if="data.hostAndPort">{{data.hostAndPort.host}}:{{data.hostAndPort.port}}</span>
                <span v-if="tabs.dashboard.connInfo.redisRunMode === 'cluster' && data.role == 'master' ">
                  <!-- 集群模式显示槽位信息 -->
                  {{data.slotStart}} - {{data.slotEnd}}
                </span>

<!--                <el-button type="text" size="small"  class="text-danger " @click="loadNodeInfo(data)" >节点信息</el-button>-->
              </div>
            </el-tree>
          </el-col>
          <el-col :span="15" class="margin-left" v-show="nodeInfoTabs.nodeId">
            <div>当前节点:
              <span v-if="nodeInfoTabs.node.hostAndPort">{{nodeInfoTabs.node.hostAndPort.host}}:{{nodeInfoTabs.node.hostAndPort.port}}</span>
              <span v-else>{{nodeInfoTabs.nodeId}}</span>
            </div>
            <el-tabs class=""  :active-name="nodeInfoTabs.activeTabName" @tab-click="switchNodeInfoTab">
              <el-tab-pane name="clients" :label="nodeInfoTabs.clients.title">
                <span style="display: block" class="margin-bottom"><b>总连接数: </b>{{nodeInfoTabs.clients.data.length}}</span>
                <el-table
                  :data="clients"
                  border
                  stripe
                  style="width: 100%"
                  size="mini"
                  height="400"
                >
                  <el-table-column
                    prop="id"
                    label="id"/>
                  <el-table-column
                    label="client" sortable
                    width="150"
                  >
                    <template slot-scope="scope">
                      <span>{{scope.row.connect.host + ':' + scope.row.connect.port}}</span>
                    </template>
                  </el-table-column>
                  <el-table-column
                    prop="age"
                    label="age" sortable/>
                  <el-table-column
                    prop="idle"
                    label="idle" sortable/>
                  <el-table-column
                    prop="cmd"
                    label="cmd" sortable/>
                  <el-table-column
                    fixed="right"
                    label="操作"
                    width="150"
                  >
                    <template slot-scope="scope">
                      <el-button type="text" class="text-danger" size="small" @click="killClient(scope.row.connect,nodeInfoTabs.nodeId)">kill</el-button>
                    </template>
                  </el-table-column>
                </el-table>
                <!--分页组件-->
                <el-pagination
                  @size-change="handleNodeInfoTabSizeChange"
                  @current-change="handleNodeInfoTabCurrentChange"
                  :current-page="nodeInfoTabs.clients.currentPage"
                  :page-size="nodeInfoTabs.clients.pageSize"
                  layout="total, sizes, prev, pager, next"
                  :total="nodeInfoTabs.clients.data.length">
                </el-pagination>
              </el-tab-pane>
              <el-tab-pane name="memory" :label="nodeInfoTabs.memory.title">
                <ul class="memory-show" style="">
                  <li><label for="">rss:</label> {{formatSizeHuman(nodeInfoTabs.memory.data.rss)}}</li>
                  <li><label for="">max:</label> {{formatSizeHuman(nodeInfoTabs.memory.data.max)}}</li>
                  <li><label for="">system:</label> {{formatSizeHuman(nodeInfoTabs.memory.data.system)}}</li>
                  <li><label for="">lua:</label> {{formatSizeHuman(nodeInfoTabs.memory.data.lua)}}</li>
                  <li><label for="">policy:</label> {{nodeInfoTabs.memory.data.policy}}</li>
                  <li><label for="">dbSize: </label> {{nodeInfoTabs.memory.data.dbSize}}</li>
                </ul>
              </el-tab-pane>
              <el-tab-pane name="slowlogs" :label="nodeInfoTabs.slowlogs.title">
                <span style="display: block" class="margin-bottom"><b>慢查询数量:</b>{{nodeInfoTabs.slowlogs.data.length}}</span>
                <el-table
                  :data="slowlogs"
                  border
                  stripe
                  style="width: 100%"
                  size="mini"
                  height="400"
                >
                  <el-table-column
                    prop="id"
                    label="id" width="80"/>

                  <el-table-column
                    label="timeStamp" sortable width="150">
                    <template slot-scope="scope">
                      <span>{{parseTime(scope.row.timeStamp)}}</span>
                    </template>
                  </el-table-column>

                  <el-table-column
                    prop="executionTime"
                    label="executionTime" sortable width="140"/>

                  <el-table-column
                    label="args" >
                    <template slot-scope="scope">
                      <span>{{scope.row.args ? scope.row.args.join(' '): ''}}</span>
                    </template>
                  </el-table-column>
                  <el-table-column
                    fixed="right"
                    label="操作"
                    width="150"
                  >
                    <template slot-scope="scope">
<!--                      <el-button type="text" class="text-danger" size="small" @click="killQuery(scope.row.id)">kill</el-button>-->
                    </template>
                  </el-table-column>
                </el-table>
                <!--分页组件-->
                <el-pagination
                  @size-change="handleNodeInfoTabSizeChange"
                  @current-change="handleNodeInfoTabCurrentChange"
                  :current-page="nodeInfoTabs.slowlogs.input.currentPage"
                  :page-size="nodeInfoTabs.slowlogs.input.pageSize"
                  layout="total, sizes, prev, pager, next"
                  :total="nodeInfoTabs.slowlogs.data.length">
                </el-pagination>
              </el-tab-pane>
            </el-tabs>
          </el-col>
        </el-row>

      </el-tab-pane>
      <el-tab-pane name="keyscan" label="数据查询">
        <el-row>
          <el-col>
            <el-form  inline size="mini">
              <el-form-item label="类加载器">
                <el-select v-model="tabs.keyscan.input.serializerParam.classloader" style="width: 150px" >
                  <el-option v-for="classloader in classloaders" :key="classloader" :value="classloader"
                             :label="classloader"/>
                </el-select>
              </el-form-item>
              <el-form-item label="key">
                <el-select v-model="tabs.keyscan.input.serializerParam.keySerializer" style="width: 100px;">
                  <el-option v-for="serializer in serializers" :key="serializer" :value="serializer" :label="serializer"/>
                </el-select>
              </el-form-item>
              <el-form-item label="value">
                <el-select v-model="tabs.keyscan.input.serializerParam.value" style="width: 100px;">
                  <el-option v-for="serializer in serializers" :key="serializer" :value="serializer" :label="serializer"/>
                </el-select>
              </el-form-item>
              <el-form-item label="hashKey">
                <el-select v-model="tabs.keyscan.input.serializerParam.hashKey" style="width: 100px;">
                  <el-option v-for="serializer in serializers" :key="serializer" :value="serializer" :label="serializer"/>
                </el-select>
              </el-form-item>
              <el-form-item label="hashValue">
                <el-select v-model="tabs.keyscan.input.serializerParam.hashValue" style="width: 100px;">
                  <el-option v-for="serializer in serializers" :key="serializer" :value="serializer" :label="serializer"/>
                </el-select>
              </el-form-item>

              <el-form-item>
                <el-button type="text"   size="mini" @click="localStorageConfig" > <i class="fa fa-floppy-o" aria-hidden="true"></i></el-button>
              </el-form-item>

            </el-form>
          </el-col>
        </el-row>

        <!-- keyscan -->
        <el-form :inline="true" @submit.native.prevent>
          <el-form-item>
            <el-checkbox v-model="tabs.keyscan.input.search.wildcardLeft">左模糊</el-checkbox>
            <el-checkbox v-model="tabs.keyscan.input.search.wildcardRight">右模糊</el-checkbox>
            <el-checkbox v-model="tabs.keyscan.input.search.fast">单KEY</el-checkbox>
          </el-form-item>
          <el-form-item>
            <el-input v-model="tabs.keyscan.input.keyScanParam.pattern" style="width: 380px" size="small" placeholder="输入 key 发起搜索" clearable
                      suffix-icon="el-icon-search" @keyup.enter.native="scanKey"/>
          </el-form-item>
          <el-form-item label="超时(ms)">
            <el-input :disabled="tabs.keyscan.input.search.fast" v-model="tabs.keyscan.input.search.timeout" size="small"  style="width: 60px" />
          </el-form-item>
          <el-form-item>
            <el-button  size="small" type="danger" @click="dropChoseKeys">批量删除</el-button>
          </el-form-item>
        </el-form>

        <el-row>
          <el-col :span="15">
            <el-table
              :data="tabs.keyscan.keyScanResult.keys"
              v-loading="tabs.keyscan.loading"
              border
              stripe
              style="width: 100%"
              size="mini"
              height="500"
              ref="keyScanTable"
            >
              <el-table-column
                type="selection"
                width="55" />
              <el-table-column
                type="index"
                width="50"/>
              <el-table-column
                prop="type"
                label="type"
                width="90" />
              <el-table-column
                prop="key"
                label="key"
                width="450" />
              <el-table-column
                prop="ttl"
                label="ttl"
                width="90" />
              <el-table-column
                prop="length"
                label="length" />

              <el-table-column
                prop="pttl"
                label="pttl"
                width="90" />
              <el-table-column
                prop="slot"
                label="slot"
                width="100"/>

              <el-table-column
                fixed="right"
                label="操作"
                width="150"
              >
                <template slot-scope="scope">
                  <el-button type="text" class="text-danger" size="small" @click="dropKeys(scope.row.key)">删除</el-button>
                  <el-button type="text" size="small" @click="readData(scope.row)">数据</el-button>
                </template>
              </el-table-column>
            </el-table>
            <el-button-group>
              <el-button plain size="mini" icon="el-icon-coordinate" @click="resetScan">重置</el-button>
              <el-button plain size="mini" :disabled="tabs.keyscan.keyScanResult.done" icon="el-icon-arrow-right" @click="nextPage">下一页</el-button>
            </el-button-group>
            cursor: {{tabs.keyscan.keyScanResult.cursor || 0}} nodeId: {{tabs.keyscan.keyScanResult.nodeId}}
          </el-col>
          <el-col :span="9" class="padding-little-left data-show" >
            <template v-if="tabs.keyscan.loadData.keyObj.type === 'string'">
              <div class="panel panel-default">
                <div class="panel-heading">{{tabs.keyscan.loadData.input.key}}({{tabs.keyscan.loadData.keyObj.type}}) 数据展示
                  <el-button class="pull-right" size="small" type="text" style="padding: 0;" @click="showJson">JSON</el-button>
                </div>
                <div class="panel-body" >
                  <div class="text">{{tabs.keyscan.loadData.data}}</div>
                </div>
              </div>
            </template>
            <template v-if="tabs.keyscan.loadData.keyObj.type === 'hash'">
              <p :title="tabs.keyscan.hashKeyScan.input.key" style="overflow-x: hidden;white-space: nowrap;text-overflow: ellipsis;">
                <el-button size="small" icon="el-icon-document-copy" type="text" @click="copyKey(tabs.keyscan.hashKeyScan.input.key,$event)"  class="margin-right"/>
                <b>key: </b>
                <span class="text-more">{{tabs.keyscan.hashKeyScan.input.key}} </span>
              </p>
              <p class="padding-big-left"><b>数据量: </b>{{tabs.keyscan.loadData.keyObj.length}}</p>
              <el-row>
                <el-col :span="18">
                  <el-input suffix-icon="el-icon-search" placeholder="搜索 hashKey " v-model="tabs.keyscan.hashKeyScan.input.pattern"
                            @keyup.enter.native="scanHashKey" size="small"/>
                </el-col>
                <el-col :span="5">
                  <el-button size="small" >选中删除</el-button>
                </el-col>
              </el-row>
              <el-table
                :data="hashScanResult"
                border
                stripe
                style="width: 100%"
                height="300"
                size="mini"
                ref="hashKeyScanTable"
                highlight-current-row
              >
                <el-table-column
                  type="index"
                  width="50"/>
                <el-table-column type="selection" width="55" />
                <el-table-column prop="field" label="field" />
                <el-table-column prop="value" label="value" />
                <el-table-column
                  fixed="right"
                  label="操作"
                  width="150"
                >
                  <template slot-scope="scope">
                    <el-button type="text" size="small" @click="dropFields(scope.row.field)">删除</el-button>
                  </template>
                </el-table-column>
              </el-table>
              <el-button-group>
                <el-button plain size="mini" icon="el-icon-coordinate" @click="resetScanHashKey">重置</el-button>
                <el-button plain size="mini" :disabled="tabs.keyscan.hashKeyScan.hashKeyScanResult.finish"  icon="el-icon-arrow-right" @click="scanHashKeyNextPage">下一页</el-button>
              </el-button-group>
              cursor: {{tabs.keyscan.hashKeyScan.hashKeyScanResult.cursor}}
            </template>
            <template v-if="tabs.keyscan.loadData.keyObj.type === 'list'">
              <p>
                <b>key:</b> {{tabs.keyscan.loadData.input.key}}
                <b>数据量: </b>{{tabs.keyscan.loadData.keyObj.length}}
                <el-checkbox v-model="tabs.keyscan.loadData.input.all" @change="loadDataRequest">所有数据</el-checkbox>
              </p>
              <div class="margin-little-top">
                <el-checkbox v-model="tabs.keyscan.loadData.input.rangeParam.enable">开启</el-checkbox>
                <el-input-number :disabled="rangeParamDisabled" v-model="tabs.keyscan.loadData.input.rangeParam.start" style="width: 120px" size="small" :min="0"
                                 :max="tabs.keyscan.loadData.keyObj.length"/>
                <el-input-number :disabled="rangeParamDisabled" v-model="tabs.keyscan.loadData.input.rangeParam.stop" style="width: 120px" size="small" :min="0"
                                 :max="tabs.keyscan.loadData.keyObj.length"/>
                <el-button plain :disabled="rangeParamDisabled" size="small" @click="loadDataRequest">加载数据</el-button>
              </div>
              <div class="panel panel-default">
                <div class="panel-heading">数据展示
                  <el-button class="pull-right" size="small" type="text" style="padding: 0;" @click="showJson">JSON</el-button>
                </div>
                <div class="panel-body" >
                  <div class="text">{{tabs.keyscan.loadData.data}}</div>
                </div>
              </div>
            </template>
            <template v-if="tabs.keyscan.loadData.keyObj.type === 'set'">
              <p style="margin-top: 0">
                <b>key:</b> {{tabs.keyscan.loadData.keyObj.key}}
                <b>数据量: </b>{{tabs.keyscan.loadData.keyObj.length}}
                <el-checkbox v-model="tabs.keyscan.loadData.input.all" @change="loadDataRequest">所有数据</el-checkbox>
              </p>
              <el-row class="">
                <el-col :span="14">
                  <el-input v-model="tabs.keyscan.set.input.otherKeys" placeholder="另外的 KEY,多个用逗号分隔 " size="small" class="margin-bottom"/>
                </el-col>
                <el-col :span="10">
                  <el-button-group >
                    <el-button :disabled="!!!tabs.keyscan.set.input.otherKeys" @click="collectionOperation('inter')" type="plain" size="small" >交集</el-button>
                    <el-button :disabled="!!!tabs.keyscan.set.input.otherKeys" @click="collectionOperation('union')" type="plain" size="small">并集</el-button>
                    <el-button :disabled="!!!tabs.keyscan.set.input.otherKeys" @click="collectionOperation('diff')" type="plain" size="small">差集</el-button>
                  </el-button-group>
                </el-col>
              </el-row>

              <!-- set 数据搜索-->
              <el-row >
                <el-col :span="3">
                  <el-checkbox size="mini" v-model="tabs.keyscan.loadData.input.all" @change="loadDataRequest">所有</el-checkbox>
                </el-col>
                <el-col :span="11">
                  <el-input :disabled="tabs.keyscan.loadData.input.all" suffix-icon="el-icon-search" placeholder="搜索 " v-model="tabs.keyscan.loadData.input.keyScanParam.pattern"
                            @keyup.enter.native="loadDataRequest" size="mini"/>
                </el-col>
                <el-col :span="10">
                  <el-button-group>
                    <el-button :disabled="tabs.keyscan.loadData.input.all" plain size="mini" icon="el-icon-coordinate" @click="resetScanSetOrZSetKey">重置</el-button>
                    <el-button  plain size="mini" :disabled="tabs.keyscan.set.scanResult.finish || tabs.keyscan.loadData.input.all" icon="el-icon-arrow-right" @click="scanSetKeyNextPage">下一页</el-button>
                  </el-button-group>

                </el-col>
              </el-row>
              <div class="panel panel-default margin-little-top">
                <div class="panel-heading">数据展示
                  <el-button class="pull-right" size="small" type="text" style="padding: 0;" @click="showJson">JSON</el-button>
                </div>
                <div class="panel-body" >
                  <p v-for="item in tabs.keyscan.loadData.data">{{item}}</p>
                </div>
              </div>
            </template>
            <template v-if="tabs.keyscan.loadData.keyObj.type === 'zset'">
              <p style="margin-top: 0">
                <b>key:</b> {{tabs.keyscan.loadData.keyObj.key}}
                <b>数据量: </b>{{tabs.keyscan.loadData.keyObj.length}}
                <el-checkbox v-model="tabs.keyscan.loadData.input.all" @change="loadDataRequest">所有数据</el-checkbox>
              </p>
              <div class="margin-little-top">
                <label for="">区间范围查找:</label>
                <el-checkbox v-model="tabs.keyscan.loadData.input.rangeParam.enable">开启</el-checkbox>
                <el-input-number :disabled="rangeParamDisabled" v-model="tabs.keyscan.loadData.input.rangeParam.start" style="width: 120px" size="small" :min="0" :max="tabs.keyscan.loadData.keyObj.length"/>
                <el-input-number :disabled="rangeParamDisabled" v-model="tabs.keyscan.loadData.input.rangeParam.stop" style="width: 120px" size="small" :min="0" :max="tabs.keyscan.loadData.keyObj.length"/>
                <el-button plain :disabled="rangeParamDisabled" size="small" @click="loadDataRequest">加载数据</el-button>
              </div>
              <div class="margin-little-top">
                <label for="">分数范围查找:</label>
                <el-checkbox v-model="tabs.keyscan.loadData.input.scoreRangeParam.enable">开启</el-checkbox>
                <el-input-number :disabled="scoreRangeParamDisabled" v-model="tabs.keyscan.loadData.input.scoreRangeParam.min" style="width: 120px" :precision="2" size="small" :min="0" />
                <el-input-number :disabled="scoreRangeParamDisabled" v-model="tabs.keyscan.loadData.input.scoreRangeParam.max" style="width: 120px" :precision="2" size="small" :min="0" />
                <el-button plain :disabled="scoreRangeParamDisabled" size="small" @click="loadDataRequest">加载数据</el-button>
              </div>
              <el-row>
                <el-col :span="14">
                  <el-input suffix-icon="el-icon-search" placeholder="搜索 " v-model="tabs.keyscan.loadData.input.keyScanParam.pattern"
                            @keyup.enter.native="loadDataRequest" size="small"/>
                </el-col>
                <el-col :span="10">
                  <el-button-group>
                    <el-button plain size="mini" icon="el-icon-coordinate" @click="resetScanSetOrZSetKey">重置</el-button>
                    <el-button plain size="mini" :disabled="tabs.keyscan.zset.scanResult.finish" icon="el-icon-arrow-right" @click="scanZSetKeyNextPage">下一页</el-button>
                  </el-button-group>

                </el-col>
              </el-row>
              <div class="panel panel-default">
                <div class="panel-heading">数据展示
                  <el-button class="pull-right" size="small" type="text" style="padding: 0;" @click="showJson">JSON</el-button>
                </div>
                <div class="panel-body" >
                  <p v-for="item in tabs.keyscan.loadData.data">{{item}}</p>
                </div>
              </div>
            </template>
          </el-col>
        </el-row>

      </el-tab-pane>
    </el-tabs>

    <!-- json 格式化展示 -->
    <el-drawer
      :with-header="false"
      :visible.sync="drawer.visible"
      direction="rtl"
    >
      <json-editor :json="drawer.json"/>
    </el-drawer>
  </div>
</template>

<script>
  import core from '../../api/core'
  import redis from '../../api/redis'
  import JsonEditor from '@/components/JsonEditor'
  import ListGroup from '@/components/ListGroup'
  import {parseTime,formatSizeHuman} from "../../utils";

  import clip from '@/utils/clipboard'
  import ScrollPane from "@/layout/components/TagsView/ScrollPane"; // use clipboard directly

  export default {
    name: 'redis',
    components: {ScrollPane, JsonEditor, ListGroup },
    data() {
      return {
        connParam: {
          connName: null,
          index: 0
        },
        connects: [],
        defaultProps: {
          children: 'slaveNodes',
          label: 'label'
        },
        tabs:{
          activeTabName: 'keyscan',
          dashboard:{
            connInfo:{
              redisRunMode: null,
              masterNodes: []
            }
          },
          keyscan:{
            loading: false,
            input: {
              search: {
                wildcardLeft: true,
                wildcardRight: true,
                timeout: -1,
                fast: false,
                nodeId: null
              },
              keyScanParam: {
                pattern: null,
                limit: 20,
                cursor: 0
              },
              serializerParam: {
                keySerializer: 'string',
                value: 'string',
                hashKey: 'string',
                hashValue: 'string',
                classloaderName: null
              }
            },
            set: {
              input: {
                otherKeys: null
              },
              scanResult: {
                cursor: 0,
              }
            },
            zset: {
              // 专用于 zset 的输入和输出
              scanResult: {
                cursor: 0
              }
            },
            keyScanResult: {},
            hashKeyScan: {
              loading: false,
              input:{
                key: null,
                all: false,
                fields: [],
                pattern: '*',
                limit: 20,
                cursor: 0
              },
              hashKeyScanResult: {
                data:{},
                fields: [],
                cursor: 0
              }
            },
            loadData:{
              loading: false,
              keyObj: {},
              input:{
                key: null,
                all: false,
                keyScanParam: {
                  pattern: '*',
                  limit: 20,
                  cursor: 0
                },
                rangeParam:{
                  enable: false,
                  start: 0 ,
                  stop: 0
                },
                scoreRangeParam:{
                  enable: false,
                  min: 0 ,
                  max: 0
                }
              },
              data: null,
            }
          }
        },
        nodeInfoTabs:{
          activeTabName: 'memory',
          loading: false,
          nodeId: null,
          node:{},
          clients:{
            title:'客户端连接',
            data:[],
            input:{
              currentPage: 1,
              pageSize: 20,
            }
          },
          memory:{
            title:'内存占用',
            data: {}
          },
          slowlogs:{
            title:'慢查询',
            data: [],
            input:{
              currentPage: 1,
              pageSize: 20,
            }
          }
        },
        serializers: [],
        classloaders: [],
        drawer: {
          visible: false,
          json: null
        }
      }
    },
    mounted() {
      this.reloadAllConnects();

      // 加载所有的序列化工具和类加载器工具
      core.classloaders().then(res => {
        this.classloaders = res.data
      })
      core.serializers().then(res => {
        this.serializers = res.data
      })

      // 加载本地保存的配置,如果之前有保存的话
      let config = this.$storeLocal.get('redis.config')
      if (config) {
        Object.assign(this.tabs.keyscan.input.serializerParam, config)
      }
    },
    methods: {
      switchTab(tab,event){
        this.tabs.activeTabName = tab.name;
        switch (tab.name){
          case 'dashboard':

            break;
        }
      },
      collectionOperation(op){
        let otherKeys = this.tabs.keyscan.set.input.otherKeys.split(',');
        let keys = [...otherKeys,this.tabs.keyscan.loadData.input.key].join(',');
        redis.collectionMethods(this.connParam,keys,op,this.tabs.keyscan.input.serializerParam).then(res => {
          this.tabs.keyscan.loadData.data = res.data;
        })
      },
      showJson(){
        try{
          if (typeof(this.tabs.keyscan.loadData.data) === 'object'){
            this.drawer.json = this.tabs.keyscan.loadData.data
          }else{
            this.drawer.json = JSON.parse(this.tabs.keyscan.loadData.data);
          }

          this.drawer.visible = true;
        }catch (e) {
          this.$message(e.toString());
          console.log(this.tabs.keyscan.loadData.data)
        }

      },
      localStorageConfig() {
        this.$storeLocal.set('redis.config', this.tabs.keyscan.input.serializerParam)
        this.$message({type:'success',message:'个人配置保存成功,下次直接使用此配置'})
      },
      parseTime,formatSizeHuman,
      copyKey(text, event){
        clip(text, event)
      },
      reloadAllConnects(){
        core.moduleConnects('redis').then(res => {
          this.connects = res.data
          if (this.connects && this.connects.length > 0) {
            this.switchConnect(this.connects[0])
          }
        })
      },
      switchIndex(index){
        this.connParam.index = index;
        this.loadConnect();
      },
      switchConnect(connect){
        this.connParam.connName = connect;
        this.loadConnect();
      },
      loadConnect(){
        // 加载当前连接信息
        redis.connInfo(this.connParam).then(res => {
          Object.assign(this.tabs.dashboard.connInfo,res.data);

          this.scanKey();
        });
      },
      scanKey(){
        let scanTabInput = this.tabs.keyscan.input;

        let scanParam = Object.assign({},scanTabInput.keyScanParam);
        // 如果需要支持模糊, 在key 两边加上 * 号
        if (scanParam.pattern){
          if (scanTabInput.search.wildcardLeft ) {
            scanParam.pattern= '*' + scanParam.pattern
          }
          if (scanTabInput.search.wildcardRight ) {
            scanParam.pattern = scanParam.pattern + '*'
          }
        }else{
          scanParam.pattern = '*';
        }
        scanParam.timeout = scanTabInput.search.timeout;
        scanParam.fast = scanTabInput.search.fast;

        this.tabs.keyscan.loading = true;
        redis.scan(this.connParam,scanParam,scanTabInput.serializerParam).then(res => {
          this.tabs.keyscan.loading = false;
          this.tabs.keyscan.keyScanResult = res.data;
        }).catch(res => {
          this.tabs.keyscan.loading = false;
        })
      },
      dropChoseKeys(){
        let selection = this.$refs.keyScanTable.selection;
        if (selection.length === 0){
          this.$message('选中 key 来删除');
          return ;
        }
        let keys = selection.map(item => item.key);
        this.$confirm('确定删除 ' + selection.length + ' 个 key 吗,此操作不可逆?', '警告', { type: 'warning' }).then(() => {
          redis.delKeys(this.connParam,keys,this.tabs.keyscan.input.serializerParam).then(res => {
            this.scanKey();
          })
        }).catch(() => {})
      },
      dropChoseFields(){
        let selection = this.$refs.hashKeyScanTable.selection;
        if (selection.length === 0){
          this.$message('选中 key 来删除');
          return ;
        }
        let fields = selection.map(item => item.field);
        this.$confirm('确定删除 ' + selection.length + ' 个 key 吗,此操作不可逆?', '警告', { type: 'warning' }).then(() => {
          redis.delFields(this.connParam,this.tabs.keyscan.hashKeyScan.input.key,fields,this.tabs.keyscan.input.serializerParam).then(res => {
            this.scanHashKey();
          })
        }).catch(() => {})
      },
      // 扫描 key 时下一页
      nextPage(){
        let scanTabInput = this.tabs.keyscan.input;

        scanTabInput.search.nodeId = this.tabs.keyscan.keyScanResult.nodeId;
        scanTabInput.keyScanParam.cursor = this.tabs.keyscan.keyScanResult.cursor;
        this.scanKey();
      },
      resetScan(){
        let scanTabInput = this.tabs.keyscan.input;

        scanTabInput.search.nodeId = null;
        scanTabInput.keyScanParam.cursor = '0';
        this.scanKey();
      },
      dropKeys(keys){
        if (keys && typeof keys === 'string') {
          this.$confirm('确定删除 ' + keys + ' 此操作不可逆?', '警告', { type: 'warning' }).then(() => {
            console.log('删除 key',keys)
            redis.delKeys(this.connParam, [keys],this.tabs.keyscan.input.serializerParam).then(res => {
              this.scanKey();
            })
          }).catch(() => {
          })
        } else if (keys) {
          this.$confirm('再次确认,将删除' + keys.length + '个 key 此操作不可逆?', '警告', { type: 'warning' }).then(() => {
            redis.delKeys(this.connParam, keys,this.tabs.keyscan.input.serializerParam).then(res => {
              this.scanKey()
            })
          }).catch(() => {
          })
        }
      },
      readData(row){
        let keyscanTab = this.tabs.keyscan;

        keyscanTab.loadData.input.key = row.key;
        keyscanTab.loadData.keyObj = row;

        switch (row.type) {
          case 'string':
            // string 类型,直接加载数据
            redis.readData(this.connParam,row.key,keyscanTab.input.serializerParam).then(res => {
              keyscanTab.loadData.data = res.data;
            });
            break;
          case 'hash':
            keyscanTab.hashKeyScan.input.key = row.key;
            this.resetScanHashKey();
            break;
          case 'list':
            this.tabs.keyscan.loadData.input.rangeParam.start = 0 ;
            this.tabs.keyscan.loadData.input.rangeParam.stop = 10 ;
            this.loadDataRequest();
              break;
          case 'set':
          case 'zset':
            this.resetScanSetOrZSetKey();
            break;
        }

      },
      scanHashKey(){
        let hashKeyScan = this.tabs.keyscan.hashKeyScan;
        hashKeyScan.loading = true;
        redis.hscan(this.connParam,hashKeyScan.input,this.tabs.keyscan.input.serializerParam).then(res => {
          hashKeyScan.loading = false;
          hashKeyScan.hashKeyScanResult = res.data;
        }).catch(res => {
          hashKeyScan.loading = false;
        })
      },
      scanHashKeyNextPage(){
        let hashKeyScan = this.tabs.keyscan.hashKeyScan;
        hashKeyScan.input.cursor = hashKeyScan.hashKeyScanResult.cursor;
        this.scanHashKey();
      },
      scanSetKeyNextPage(){
        let loadData = this.tabs.keyscan.loadData;
        loadData.input.keyScanParam.cursor = this.tabs.keyscan.set.scanResult.cursor;
        this.loadDataRequest();
      },
      scanZSetKeyNextPage(){
        let loadData = this.tabs.keyscan.loadData;
        loadData.input.keyScanParam.cursor = this.tabs.keyscan.zset.scanResult.cursor;
        this.loadDataRequest();
      },
      resetScanHashKey(){
        let keyscanTab = this.tabs.keyscan;
        Object.assign(keyscanTab.hashKeyScan.input,{pattern:'*',cursor:'0',limit:20})
        this.scanHashKey();
      },
      resetScanSetOrZSetKey(){
        let loadData = this.tabs.keyscan.loadData;
        Object.assign(loadData.input.keyScanParam,{pattern:'*',cursor:'0',limit:20})
        this.loadDataRequest();
      },
      dropFields(fields){
        let keyscan = this.tabs.keyscan;
        if (fields && typeof fields === 'string') {
          this.$confirm('确定删除 ' + fields + ' 此操作不可逆?', '警告', { type: 'warning' }).then(() => {
           redis.delFields(this.connParam,keyscan.hashKeyScan.input.key,[fields],keyscan.input.serializerParam).then(res => {
            this.scanHashKey();
           })
          }).catch(() => {
          })
        } else if (fields) {
          this.$confirm('再次确认,将删除' + fields.length + '个 field 此操作不可逆?', '警告', { type: 'warning' }).then(() => {
            redis.delFields(this.connParam,keyscan.hashKeyScan.input.key,fields,keyscan.input.serializerParam).then(res => {
              this.scanHashKey();
            })
          }).catch(() => {
          })
        }
      },
      loadDataRequest(){
        let loadData = this.tabs.keyscan.loadData;
        loadData.loading = true;
        redis.readData(this.connParam,loadData.input.key,
          this.tabs.keyscan.input.serializerParam,loadData.input.all,
          loadData.input.keyScanParam,loadData.input.rangeParam,
          loadData.input.scoreRangeParam).then(res => {
          loadData.loading  = false;
          if (loadData.keyObj.type === 'set' && 'cursor' in res.data){
            this.tabs.keyscan.set.scanResult = res.data;
            loadData.data = res.data.members;
          }else if (loadData.keyObj.type === 'zset' && 'cursor' in res.data){
            this.tabs.keyscan.zset.scanResult = res.data;
            loadData.data = res.data.tuples;
          }else{
            loadData.data = res.data;
          }
        }).catch(res => {
          loadData.loading  = false;
        })
      },
      switchNodeInfoTab(tab,event){
        this.nodeInfoTabs.activeTabName = tab.name;

        switch (tab.name){
          case 'clients':
            redis.clients(this.connParam,this.nodeInfoTabs.nodeId).then(res => {
              this.nodeInfoTabs.clients.data = res.data;
            })
            break;
          case 'memory':
            redis.memory(this.connParam,this.nodeInfoTabs.nodeId).then(res => {
              this.nodeInfoTabs.memory.data = res.data;
            })
            break;
          case 'slowlogs':
            redis.slowlogs(this.connParam,this.nodeInfoTabs.nodeId).then(res => {
              this.nodeInfoTabs.slowlogs.data = res.data;
            })
            break;
        }
      },
      clickNode(data,node,el){
        this.loadNodeInfo(data);
      },
      loadNodeInfo(node){
        this.nodeInfoTabs.nodeId = node.id;
        this.nodeInfoTabs.node = node;
        this.switchNodeInfoTab({name:this.nodeInfoTabs.activeTabName});
      },
      killClient(client,nodeId){
        redis.killClient(this.connParam,client,nodeId);
        this.switchNodeInfoTab({name:'clients'});
      },
      killQuery(id){

      },
      handleNodeInfoTabSizeChange(val){
        switch (this.nodeInfoTabs.activeTabName){
          case 'clients':
            this.nodeInfoTabs.clients.input.pageSize = val;
            break;
          case 'slowlogs':
            this.nodeInfoTabs.slowlogs.input.pageSize = val;
        }
      },
      handleNodeInfoTabCurrentChange(val){
        switch (this.nodeInfoTabs.activeTabName){
          case 'clients':
            this.nodeInfoTabs.clients.input.currentPage = val;
            break;
          case 'slowlogs':
            this.nodeInfoTabs.slowlogs.input.currentPage = val;
        }
      }

    },
    computed: {
      dbsComputed(){
        let connInfo = this.tabs.dashboard.connInfo;
        if (connInfo){
          if (connInfo.redisRunMode === 'cluster'){
            return [0] ;
          }
          if (connInfo.masterNodes.length === 0){
            return [0];
          }

          let masterNode = connInfo.masterNodes[0];

          let array = [];
          for (let i = 0; i < masterNode.dbs; i++) {
            array.push(i);
          }
          return array;
        }
        return [0];
      },
      clients(){
        let clients = this.nodeInfoTabs.clients;
        if (!clients.data){
          return [];
        }
        let start = (clients.input.currentPage - 1) * clients.input.pageSize;
        let end = clients.input.currentPage * clients.input.pageSize;
        if (end > clients.data.length){
          end = clients.data.length;
        }
        return clients.data.slice(start,end);
      },
      slowlogs(){
        let slowlogs = this.nodeInfoTabs.slowlogs;
        if (!slowlogs.data){
          return [];
        }
        let start = (slowlogs.input.currentPage - 1) * slowlogs.input.pageSize;
        let end = slowlogs.input.currentPage * slowlogs.input.pageSize;
        if (end > slowlogs.data.length){
          end = slowlogs.data.length;
        }
        return slowlogs.data.slice(start,end);
      },
      hashScanResult(){
        let hashScanResult = this.tabs.keyscan.hashKeyScan.hashKeyScanResult;
        if (hashScanResult.data){
          let values = [];
          for(let field in hashScanResult.data){
            values.push({field:field,value:hashScanResult.data[field]})
          }
          return values;
        }
        return [];
      },
      rangeParamDisabled(){
        return this.tabs.keyscan.loadData.input.all || !this.tabs.keyscan.loadData.input.rangeParam.enable;
      },
      scoreRangeParamDisabled(){
        return this.tabs.keyscan.loadData.input.all || !this.tabs.keyscan.loadData.input.scoreRangeParam.enable;
      }
    }
  }
</script>

<style scoped>
.custom-tree-node{
  display: flex;
  align-items: center;
  width: 100%;
}
.custom-tree-node>button{
  margin-left: auto;
}
.memory-show{
  list-style-type: none;font-size: 15px;line-height: 2;
}
.memory-show li>label{
  display: inline-block;
  text-align: right;
  width: 80px;
}
.data-show .panel-body{
  min-height: 370px;
  max-height: 370px;
  overflow-y: scroll
}
</style>
